home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 May: Tool Chest / Dev.CD May 98 TC.toast / Tool Chest / Development Kits / HyperCard Related / APDA HyperCard Toolkits / CD Audio Toolkit 1.0 / Source / CDTOCLines.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-07  |  6.6 KB  |  267 lines  |  [TEXT/MPS ]

  1. /*
  2.     CDTOCLines - An XFCN to read the table of contents of a CD
  3.     ©Apple Computer, Inc. 1988
  4.     All Rights Reserved.
  5.     
  6.     88/10/08    BL°B    First Version
  7.  
  8.     To compile and link this file using Macintosh Programmer's Workshop,
  9.  
  10.     C -q2 CDTOCLines.c
  11.     link -sn Main=CDTOCLines -sn STDIO=CDTOCLines ∂
  12.          -sn INTENV=CDTOCLines -rt XFCN=42 ∂
  13.          -m CDTOCLINES CDTOCLines.c.o "{CLibraries}"CRuntime.o ∂
  14.          "{CLibraries}"StdCLib.o ∂
  15.          -o HyperCommands
  16.          
  17.     This link directive puts the XCMD in the file "HyperCommands".
  18.     Substitute the name of the stack you want it in.  To move XCMDs
  19.     between stacks, use ResEdit.  They can be in an individual stack,
  20.     the Home stack, the HyperCard application, or the System File.
  21.     
  22. */
  23.  
  24. #include <cd.h>
  25.  
  26. typedef struct {
  27.     long    minute;
  28.     long    second;
  29.     long    block;
  30. } TrackInfo;
  31.  
  32. /* prototype definitions for functions */
  33. OSErr    GetNumberTracks(short, short *);
  34. OSErr    ReadTOC(short, short, TrackInfo *);
  35. void    CFormatString(char *, long *, long);
  36.  
  37. /* **** WARNING:  DO NOT USE GLOBAL VARIABLES! **** */
  38.  
  39.  
  40. /************************************************************************
  41.  *
  42.  *  Function:        CDTOCLines
  43.  *
  44.  *  Purpose:        Read table of contents
  45.  *
  46.  *  Returns:        result of driver call to ReadTOC
  47.  *                    normally 0, but could have parameter error or
  48.  *                    other error if non-existent block is specified
  49.  *
  50.  *  Side Effects:
  51.  *
  52.  *  Description:    We need no parameter:
  53.  *                    Get the ioRefNum that we got from previously calling
  54.  *                    CDOpen() by accessing the famous global.
  55.  *                    Read the table of contents into our buffer.  Format
  56.  *                    our buffer, adding a carriage return between tracks.
  57.  *
  58.  ************************************************************************/
  59. pascal void
  60. CDTOCLines(paramPtr)
  61. XCmdBlockPtr    paramPtr;
  62. {
  63.     Str31    returnString;
  64.     OSErr    result;
  65.     short    ioRefNum;
  66.     Handle    refHandle;
  67.     
  68.     short    numberTracks;
  69.     TrackInfo    **trackHandle;
  70.     
  71.     Handle    formatString;
  72.         
  73.     /* Must be no parameter */
  74.     if ((paramPtr->paramCount) != 0)
  75.     {
  76.         /* Report error in parameters by returning -1 */
  77.         NumToStr(paramPtr, (long) -1, &returnString);
  78.         paramPtr->returnValue = PasToZero(paramPtr, (StringPtr) &returnString);
  79.         return;
  80.     }
  81.     
  82.     /* Get the global ioRefNum and convert it. */
  83.     refHandle = GetGlobal(paramPtr, GLOBALNAME);
  84.     ioRefNum = atoi(*(refHandle));
  85.     DisposHandle(refHandle);
  86.     ioRefNum &= 0xFFFF;            /* remove vRefNum; not needed. */
  87.     
  88.     result = GetNumberTracks(ioRefNum, &numberTracks);
  89.     
  90.     trackHandle = (TrackInfo **) 0;        /* so final DisposHandle will work */
  91.     
  92.     if (result == noErr)
  93.     {
  94.         trackHandle = NewHandle(numberTracks * sizeof(TrackInfo));
  95.         if (trackHandle == (TrackInfo **) 0)
  96.             result = MemError();
  97.         HLock(trackHandle);
  98.     }
  99.     
  100.     if (result == noErr)
  101.         result = ReadTOC(ioRefNum, numberTracks, *trackHandle);
  102.  
  103.     formatString = NewHandle(1000);    /* we can 99 tracks * 9 bytes per track */
  104.     if (formatString == nil)
  105.         result = MemError();
  106.  
  107.     if (result == noErr)
  108.     {
  109.         HLock(formatString);
  110.         CFormatString((char *)*formatString, *trackHandle, numberTracks * 3);
  111.         HUnlock(formatString);
  112.         paramPtr->returnValue = formatString;    /* let HyperCard do the dispose */
  113.     }
  114.     else
  115.     {
  116.         /* We had an error.  Convert result to string & return it */
  117.         NumToStr(paramPtr, (long) result, &returnString);
  118.         paramPtr->returnValue = PasToZero(paramPtr, (StringPtr) &returnString);
  119.         if (formatString != nil)
  120.             DisposHandle(formatString);    /* only dispose of this if we aren't */
  121.                                         /* returning it to Hypercard */
  122.     }
  123.  
  124.     if (trackHandle != (TrackInfo **) 0)
  125.     {
  126.         HUnlock(trackHandle);
  127.         DisposHandle(trackHandle);
  128.     }
  129. }
  130.  
  131.  
  132.  
  133. /************************************************************************
  134.  *
  135.  *  Function:        GetNumberTracks
  136.  *
  137.  *  Purpose:        report how many tracks are on this CD
  138.  *
  139.  *  Returns:        OSErr.  Probably either
  140.  *                        noErr        everything's hunky-dory!
  141.  *                        paramErr    you messed up the call somehow.
  142.  *
  143.  *  Side Effects:    none
  144.  *
  145.  *  Description:    Simply call the driver.
  146.  *
  147.  ************************************************************************/
  148. OSErr
  149. GetNumberTracks(refNum, numberTracks)
  150. short    refNum;
  151. short    *numberTracks;
  152. {
  153.     CDParam    myPB;
  154.     OSErr    result;
  155.     
  156.     myPB.ioCompletion = 0;
  157.     myPB.ioNamePtr = (char *) 0;
  158.     myPB.ioVRefNum = 1;
  159.     myPB.ioCRefNum = refNum;
  160.     myPB.csCode = READTOC;
  161.     myPB.csParam[0] = 0;
  162.     myPB.csParam[1] = 1;
  163.     
  164.     result = PBControl(&myPB, false);
  165.     
  166.     if (result == noErr)
  167.         *numberTracks = (short) BCD2DECIMAL(myPB.csParam[1]);
  168.     return result;
  169. }
  170.  
  171. /************************************************************************
  172.  *
  173.  *  Function:        ReadTOC
  174.  *
  175.  *  Purpose:        read table of contents
  176.  *
  177.  *  Returns:        OSErr
  178.  *                    usually 0, but can be negative if driver returns
  179.  *                    an error
  180.  *
  181.  *  Side Effects:    fills trackInfo with absolute minute, second, block
  182.  *                    for each track.
  183.  *
  184.  *  Description:    We depend upon the trackInfo array already being
  185.  *                    allocated by the calling routine.
  186.  *                    Allocate the buffer to pass to
  187.  *                    the READTOC call.  Call the driver.  Loop through
  188.  *                    the READTOC buffer, converting values into the
  189.  *                    final buffer.
  190.  *
  191.  ************************************************************************/
  192. OSErr
  193. ReadTOC(refNum, numberTracks, trackInfo)
  194. short        refNum;
  195. short        numberTracks;
  196. TrackInfo    trackInfo[];
  197. {
  198.     CDPlay3Param    myPB;
  199.     OSErr    result;
  200.     char    *track;
  201.     short    trackSize;
  202.     short    i, j;
  203.     
  204.     trackSize = numberTracks * 4;        /* 4 bytes per track in call */
  205.     track = NewPtr(trackSize);
  206.     myPB.ioCompletion = 0;
  207.     myPB.ioNamePtr = (char *) 0;
  208.     myPB.ioVRefNum = 1;
  209.     myPB.ioCRefNum = refNum;
  210.     myPB.csCode = READTOC;
  211.     myPB.readType = BUFADDR;
  212.     myPB.bufAddr = track;
  213.     myPB.bufferLength = trackSize;
  214.     myPB.track = 1;
  215.     
  216.     result = PBControl(&myPB, false);
  217.     for (i = 0; i < numberTracks; i++)
  218.     {
  219.         j = i * 4;
  220.         trackInfo[i].minute = (long) BCD2DECIMAL(track[j+1]);
  221.         trackInfo[i].second = (long) BCD2DECIMAL(track[j+2]);
  222.         trackInfo[i].block = (long) BCD2DECIMAL(track[j+3]);
  223.     }
  224.     DisposPtr(track);
  225.     return result;
  226. }
  227.  
  228.  
  229. /************************************************************************
  230.  *
  231.  *  Function:        CFormatString
  232.  *
  233.  *  Purpose:        prepare return string
  234.  *
  235.  *  Returns:        nothing
  236.  *
  237.  *  Side Effects:    creates C string from input parameters
  238.  *
  239.  *  Description:    For each of the numArgs values in num[], convert the 
  240.  *                    value to an ascii string and concatenate.
  241.  *
  242.  ************************************************************************/
  243. void
  244. CFormatString(str, num, numArgs)
  245. char    str[];
  246. long     num[];
  247. long    numArgs;
  248. {
  249.     short    i;
  250.     char    numStr[31];
  251.     
  252.     ltoa(num[0], str);
  253.     for (i = 1; i < numArgs; i++)
  254.     {
  255.         if (i % 3 == 0)
  256.             strcat(str, "\n");        /* seperate tracks by carriage returns */
  257.         else
  258.             strcat(str, ",");        /* add comma to separate items */
  259.         ltoa(num[i], numStr);
  260.         strcat(str, numStr);
  261.     }
  262. }
  263.  
  264.  
  265. /* C routines for HyperCard callbacks */
  266. #include <XCmdGlue.inc.c>
  267.